/*!
 * \file test_wt_cta_engine.cpp
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2025/01/01
 * 
 * \brief WtCtaEngine的单元测试
 * 
 * \details 测试WtCtaEngine的核心功能：
 *          - CTA策略管理
 *          - 行情数据处理
 *          - K线数据管理
 *          - 交易执行接口
 *          - 定时调度机制
 *          - 执行器集成
 */
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "../../src/WtCore/WtCtaEngine.h"
#include "../../src/WtCore/WtDtMgr.h"
#include "../../src/WtCore/CtaStraBaseCtx.h"
#include "../../src/Share/IniHelper.hpp"
#include "../../src/Includes/WTSVariant.hpp"
#include "../../src/Includes/WTSDataDef.hpp"
#include "../../src/Includes/WTSContractInfo.hpp"

using namespace wtp;
using ::testing::_;
using ::testing::Return;
using ::testing::NiceMock;
using ::testing::AtLeast;
using ::testing::Invoke;

/*!
 * \class MockCtaContext
 * \brief 模拟CTA策略上下文
 */
class MockCtaContext : public ICtaStraCtx {
public:
    MOCK_METHOD(uint32_t, id, (), (override));
    MOCK_METHOD(const char*, name, (), (override));
    MOCK_METHOD(int32_t, type, (), (override));
    MOCK_METHOD(void, on_init, (), (override));
    MOCK_METHOD(void, on_session_begin, (uint32_t), (override));
    MOCK_METHOD(void, on_session_end, (uint32_t), (override));
    MOCK_METHOD(void, on_tick, (const char*, WTSTickData*), (override));
    MOCK_METHOD(void, on_bar, (const char*, const char*, uint32_t, WTSBarStruct*), (override));
    MOCK_METHOD(void, on_schedule, (uint32_t, uint32_t), (override));
    MOCK_METHOD(bool, isInTrading, (), (override));
    MOCK_METHOD(void, enum_position, (FuncEnumCtaPosCallBack), (override));
    
    // 添加必要的默认实现
    MockCtaContext() {
        ON_CALL(*this, id()).WillByDefault(Return(1));
        ON_CALL(*this, name()).WillByDefault(Return("mock_cta"));
        ON_CALL(*this, type()).WillByDefault(Return(0));
        ON_CALL(*this, isInTrading()).WillByDefault(Return(true));
    }
};

/*!
 * \class MockDataManager
 * \brief 模拟数据管理器
 */
class MockDataManager : public WtDtMgr {
public:
    MockDataManager() : WtDtMgr() {}
    MOCK_METHOD(WTSTickData*, grab_last_tick, (const char* code), (override));
    MOCK_METHOD(WTSSessionInfo*, get_session_info, (const char* sid, bool bForce), (override));
    MOCK_METHOD(WTSCommodityInfo*, get_commodity_info, (const char* stdCode), (override));
    MOCK_METHOD(WTSContractInfo*, get_contract_info, (const char* stdCode), (override));
};

/*!
 * \class MockExecuter
 * \brief 模拟执行器
 */
class MockExecuter : public IExecCommand {
public:
    MOCK_METHOD(void, set_position, (const uint32_t* stdCode, int32_t qty), (override));
    MOCK_METHOD(void, on_position_changed, (const uint32_t* stdCode, int32_t qty), (override));
};

/*!
 * \class WtCtaEngineTest
 * \brief WtCtaEngine测试套件
 */
class WtCtaEngineTest : public ::testing::Test {
protected:
    void SetUp() override {
        engine = std::make_unique<WtCtaEngine>();
        dataMgr = std::make_shared<NiceMock<MockDataManager>>();
        
        // 创建配置
        cfg = WTSVariant::createObject();
        cfg->append("name", "cta_engine", false);
        
        // 创建模拟的会话信息
        mockSession = WTSSessionInfo::create("TRADING", "交易时段", 0);
        mockSession->addTradingSection(93000, 113000);
        mockSession->addTradingSection(133000, 150000);
        
        // 设置数据管理器的默认行为
        ON_CALL(*dataMgr, get_session_info(_, _))
            .WillByDefault(Return(mockSession));
    }
    
    void TearDown() override {
        if (cfg) cfg->release();
        if (mockSession) mockSession->release();
        if (mockTick) mockTick->release();
    }
    
    std::unique_ptr<WtCtaEngine> engine;
    std::shared_ptr<MockDataManager> dataMgr;
    std::shared_ptr<MockCtaContext> ctaContext;
    WTSVariant* cfg;
    WTSSessionInfo* mockSession = nullptr;
    WTSTickData* mockTick = nullptr;
};

/*!
 * \brief 测试CTA引擎初始化
 * 
 * \details 验证CTA引擎的初始化流程
 */
TEST_F(WtCtaEngineTest, TestEngineInitialization) {
    // 初始化引擎
    engine->init(cfg, nullptr, dataMgr.get(), nullptr, nullptr);
    
    // 验证引擎状态
    EXPECT_FALSE(engine->isInTrading());
    
    // 运行引擎（异步模式）
    engine->run(true);
    
    std::cout << "CTA引擎初始化测试通过" << std::endl;
}

/*!
 * \brief 测试策略上下文管理
 * 
 * \details 验证CTA策略上下文的添加和管理
 */
TEST_F(WtCtaEngineTest, TestContextManagement) {
    engine->init(cfg, nullptr, dataMgr.get(), nullptr, nullptr);
    
    // 创建多个策略上下文
    auto ctx1 = std::make_shared<NiceMock<MockCtaContext>>();
    auto ctx2 = std::make_shared<NiceMock<MockCtaContext>>();
    auto ctx3 = std::make_shared<NiceMock<MockCtaContext>>();
    
    ON_CALL(*ctx1, id()).WillByDefault(Return(1));
    ON_CALL(*ctx2, id()).WillByDefault(Return(2));
    ON_CALL(*ctx3, id()).WillByDefault(Return(3));
    
    ON_CALL(*ctx1, name()).WillByDefault(Return("strategy1"));
    ON_CALL(*ctx2, name()).WillByDefault(Return("strategy2"));
    ON_CALL(*ctx3, name()).WillByDefault(Return("strategy3"));
    
    // 添加策略上下文
    engine->addContext(CtaContextPtr(ctx1));
    engine->addContext(CtaContextPtr(ctx2));
    engine->addContext(CtaContextPtr(ctx3));
    
    // 期望所有策略都收到初始化调用
    EXPECT_CALL(*ctx1, on_init()).Times(1);
    EXPECT_CALL(*ctx2, on_init()).Times(1);
    EXPECT_CALL(*ctx3, on_init()).Times(1);
    
    // 触发初始化
    engine->on_init();
    
    std::cout << "策略上下文管理测试通过" << std::endl;
}

/*!
 * \brief 测试行情数据处理
 * 
 * \details 验证CTA引擎处理tick数据的能力
 */
TEST_F(WtCtaEngineTest, TestTickDataProcessing) {
    engine->init(cfg, nullptr, dataMgr.get(), nullptr, nullptr);
    
    // 创建策略上下文
    ctaContext = std::make_shared<NiceMock<MockCtaContext>>();
    engine->addContext(CtaContextPtr(ctaContext));
    
    // 创建测试tick数据
    mockTick = WTSTickData::create("SHFE.rb2501");
    mockTick->setPrice(3850.0);
    mockTick->setVolume(1000);
    
    // 订阅合约
    engine->sub_tick(1, "SHFE.rb2501");
    
    // 期望策略收到tick数据
    EXPECT_CALL(*ctaContext, on_tick("SHFE.rb2501", _))
        .Times(AtLeast(1))
        .WillOnce(Invoke([](const char* code, WTSTickData* tick) {
            EXPECT_STREQ(code, "SHFE.rb2501");
            EXPECT_EQ(tick->price(), 3850.0);
        }));
    
    // 推送tick数据
    engine->handle_push_quote(mockTick, 0);
    
    std::cout << "行情数据处理测试通过" << std::endl;
}

/*!
 * \brief 测试K线数据处理
 * 
 * \details 验证CTA引擎处理K线数据的能力
 */
TEST_F(WtCtaEngineTest, TestBarDataProcessing) {
    engine->init(cfg, nullptr, dataMgr.get(), nullptr, nullptr);
    
    // 创建策略上下文
    ctaContext = std::make_shared<NiceMock<MockCtaContext>>();
    engine->addContext(CtaContextPtr(ctaContext));
    
    // 创建测试K线数据
    WTSBarStruct bar;
    bar.date = 20250101;
    bar.time = 20250101093000;
    bar.open = 3840.0;
    bar.high = 3860.0;
    bar.low = 3835.0;
    bar.close = 3855.0;
    bar.vol = 5000;
    
    // 期望策略收到K线数据
    EXPECT_CALL(*ctaContext, on_bar("SHFE.rb2501", "m1", _, _))
        .Times(AtLeast(1))
        .WillOnce(Invoke([](const char* code, const char* period, uint32_t times, WTSBarStruct* bar) {
            EXPECT_STREQ(code, "SHFE.rb2501");
            EXPECT_STREQ(period, "m1");
            EXPECT_EQ(bar->close, 3855.0);
        }));
    
    // 推送K线数据
    engine->on_bar("SHFE.rb2501", "m1", 1, &bar);
    
    std::cout << "K线数据处理测试通过" << std::endl;
}

/*!
 * \brief 测试定时调度机制
 * 
 * \details 验证CTA引擎的定时任务调度功能
 */
TEST_F(WtCtaEngineTest, TestScheduleMechanism) {
    engine->init(cfg, nullptr, dataMgr.get(), nullptr, nullptr);
    
    // 创建策略上下文
    ctaContext = std::make_shared<NiceMock<MockCtaContext>>();
    engine->addContext(CtaContextPtr(ctaContext));
    
    // 设置当前时间
    engine->set_date_time(20250101, 93000, 0);
    
    // 期望策略收到调度事件
    EXPECT_CALL(*ctaContext, on_schedule(20250101, 93000))
        .Times(1);
    
    // 触发调度
    engine->on_schedule(20250101, 93000, 0);
    
    std::cout << "定时调度机制测试通过" << std::endl;
}

/*!
 * \brief 测试会话管理
 * 
 * \details 验证CTA引擎的交易时段管理
 */
TEST_F(WtCtaEngineTest, TestSessionManagement) {
    engine->init(cfg, nullptr, dataMgr.get(), nullptr, nullptr);
    
    // 创建策略上下文
    ctaContext = std::make_shared<NiceMock<MockCtaContext>>();
    engine->addContext(CtaContextPtr(ctaContext));
    
    uint32_t tradingDate = 20250101;
    
    // 期望策略收到会话开始事件
    EXPECT_CALL(*ctaContext, on_session_begin(tradingDate))
        .Times(1);
    
    // 触发会话开始
    engine->on_session_begin(tradingDate);
    
    // 期望策略收到会话结束事件
    EXPECT_CALL(*ctaContext, on_session_end(tradingDate))
        .Times(1);
    
    // 触发会话结束
    engine->on_session_end(tradingDate);
    
    std::cout << "会话管理测试通过" << std::endl;
}

/*!
 * \brief 测试执行器集成
 * 
 * \details 验证CTA引擎与执行器的集成
 */
TEST_F(WtCtaEngineTest, TestExecuterIntegration) {
    engine->init(cfg, nullptr, dataMgr.get(), nullptr, nullptr);
    
    // 创建模拟执行器
    auto executer = std::make_shared<NiceMock<MockExecuter>>();
    
    // 添加执行器（通过ExecMgr）
    WtExecMgr* execMgr = engine->getExecMgr();
    EXPECT_NE(execMgr, nullptr);
    
    // 测试执行器存根功能
    uint32_t stdCode = 123456;
    int32_t position = 10;
    
    // 期望执行器收到仓位变化通知
    EXPECT_CALL(*executer, on_position_changed(&stdCode, position))
        .Times(0); // 因为我们没有真正注册执行器
    
    // 通知仓位变化
    engine->on_position_changed(&stdCode, position);
    
    std::cout << "执行器集成测试通过" << std::endl;
}

/*!
 * \brief 测试多策略并发
 * 
 * \details 验证CTA引擎同时管理多个策略的能力
 */
TEST_F(WtCtaEngineTest, TestMultiStrategyParallel) {
    engine->init(cfg, nullptr, dataMgr.get(), nullptr, nullptr);
    
    const int NUM_STRATEGIES = 10;
    std::vector<std::shared_ptr<MockCtaContext>> strategies;
    
    // 创建多个策略
    for (int i = 0; i < NUM_STRATEGIES; ++i) {
        auto ctx = std::make_shared<NiceMock<MockCtaContext>>();
        ON_CALL(*ctx, id()).WillByDefault(Return(i + 1));
        ON_CALL(*ctx, name()).WillByDefault(Return(("strategy_" + std::to_string(i + 1)).c_str()));
        
        strategies.push_back(ctx);
        engine->addContext(CtaContextPtr(ctx));
    }
    
    // 创建tick数据
    auto tick = WTSTickData::create("SHFE.rb2501");
    tick->setPrice(3850.0);
    
    // 所有策略订阅同一合约
    for (int i = 0; i < NUM_STRATEGIES; ++i) {
        engine->sub_tick(i + 1, "SHFE.rb2501");
    }
    
    // 期望所有策略都收到tick数据
    for (auto& ctx : strategies) {
        EXPECT_CALL(*ctx, on_tick("SHFE.rb2501", _))
            .Times(AtLeast(1));
    }
    
    // 推送tick数据
    engine->handle_push_quote(tick, 0);
    
    tick->release();
    
    std::cout << "多策略并发测试通过，测试策略数: " << NUM_STRATEGIES << std::endl;
}

/*!
 * \brief 测试错误处理
 * 
 * \details 验证CTA引擎的错误处理能力
 */
TEST_F(WtCtaEngineTest, TestErrorHandling) {
    // 测试未初始化状态
    EXPECT_NO_THROW(engine->handle_push_quote(nullptr, 0));
    EXPECT_NO_THROW(engine->on_tick(nullptr, nullptr));
    EXPECT_NO_THROW(engine->on_bar(nullptr, nullptr, 0, nullptr));
    
    // 初始化引擎
    engine->init(cfg, nullptr, dataMgr.get(), nullptr, nullptr);
    
    // 测试空数据处理
    EXPECT_NO_THROW(engine->handle_push_quote(nullptr, 0));
    EXPECT_NO_THROW(engine->on_tick("SHFE.rb2501", nullptr));
    
    // 测试无效合约代码
    auto tick = WTSTickData::create("");
    EXPECT_NO_THROW(engine->handle_push_quote(tick, 0));
    tick->release();
    
    std::cout << "错误处理测试通过" << std::endl;
}

/*!
 * \brief 测试性能特性
 * 
 * \details 验证CTA引擎的性能表现
 */
TEST_F(WtCtaEngineTest, TestPerformanceCharacteristics) {
    engine->init(cfg, nullptr, dataMgr.get(), nullptr, nullptr);
    
    // 创建100个策略
    const int NUM_STRATEGIES = 100;
    for (int i = 0; i < NUM_STRATEGIES; ++i) {
        auto ctx = std::make_shared<NiceMock<MockCtaContext>>();
        ON_CALL(*ctx, id()).WillByDefault(Return(i + 1));
        engine->addContext(CtaContextPtr(ctx));
        engine->sub_tick(i + 1, "SHFE.rb2501");
    }
    
    // 创建tick数据
    auto tick = WTSTickData::create("SHFE.rb2501");
    tick->setPrice(3850.0);
    
    // 测试tick推送性能
    const int NUM_TICKS = 1000;
    auto start = std::chrono::high_resolution_clock::now();
    
    for (int i = 0; i < NUM_TICKS; ++i) {
        tick->setPrice(3850.0 + i);
        engine->handle_push_quote(tick, 0);
    }
    
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    
    double totalTimeMs = duration.count() / 1000.0;
    double avgTimeUs = static_cast<double>(duration.count()) / NUM_TICKS;
    
    tick->release();
    
    // 性能基准：处理1000个tick应该在100毫秒内完成
    EXPECT_LT(totalTimeMs, 100.0);
    
    std::cout << "性能特性测试通过:" << std::endl;
    std::cout << "  策略数量: " << NUM_STRATEGIES << std::endl;
    std::cout << "  Tick数量: " << NUM_TICKS << std::endl;
    std::cout << "  总耗时: " << totalTimeMs << " 毫秒" << std::endl;
    std::cout << "  平均每Tick: " << avgTimeUs << " 微秒" << std::endl;
}